/**
 * @namespace Simple methods to assert that various objects exist or are of a
 * given type.
 */
Jelo.Valid = function() {
    
    // the easy way
    Array.prototype.isArray = true;
    Function.prototype.isFunction = true;
    Number.prototype.isNumber = true;
    String.prototype.isString = true;
    
    /** @scope Jelo.Valid */
    return {
        
        /**
         * Checks whether an object exists (not necessarily truthy).
         * 
         * @param {Mixed} item The item to investiate.
         * @return {Boolean} False only for null and undefined values
         */
        is         : function(i) {
            return (typeof i === "undefined") || (i === null);
        },
        
        /**
         * Checks whether an object is an array or array subclass.
         * 
         * @param {Mixed} item The item to investiate.
         * @return {Boolean} True if item is an array or array subclass.
         */
        isArray    : function(a) {
            return a && (a.constructor == Array);
        },
        
        /**
         * Checks whether an object is "Array-like" and can probably 
         * be iterated over, looped through, etc.
         * 
         * @param {Mixed} item The item to investiate.
         * @return {Boolean} True if item is iterable.
         */
        isIterable : function(a) {
            return (typeof a == 'object' && typeof a.length == 'number');
        },
        
        /**
         * Checks whether an object is an HTML/DOM element.
         * 
         * @param {Mixed} item The item to investiate.
         * @return {Boolean} True if item is an HTMLElement-like object.
         */
        isElement  : function(e) {
            return (typeof e == "object") && (e !== null) &&
                (typeof e.tagName == "string") &&
                (typeof e.className == "string");
        },
        
        /**
         * Checks whether an object is a Function.
         * 
         * @param {Mixed} item The item to investiate.
         * @return {Boolean} True if item is a Function.
         */
        isFunction : function(f) {
            return !!f.isFunction || (f instanceof Function) ||
                (typeof f == "function");
        },
        
        /**
         * Check whether an object is a Number.
         * 
         * @param {Mixed} item The item to investiate.
         * @return {Boolean} True if item is a Number.
         */
        isNumber   : function(n) {
            return n && (!!n.isNumber || !isNaN(n));
        },
        
        /**
         * Checks whether an e-mail address is formatted correctly.
         * 
         * @param {Mixed} item The item to investiate.
         * @return {Boolean} True if item is formatted like a valid e-mail
         * address. The actual account may or may not exist. Future versions of
         * Jelo will include a check for actual e-mail accounts.
         */
        isEmail    : function(e) {
            var regex = /^[a-z0-9_\-]+(\.[_a-z0-9\-]+)*@([_a-z0-9\-]+\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)$/;
            return regex.test(e);
        }
    };
}();
